/**
 * Copyright 2008 Matthew DeLambo
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.delambo.drool.pooling;

import com.delambo.drool.interfaces.*;
import java.util.concurrent.locks.ReentrantLock;

/**
 * To increase pool node availabilty, a circular index will be maintained so any 
 * thread will start iterating through the pool array at one circular index 
 * higher than the previous thread.
 * @author delambo
 */
public final class CircularIndexPointer_Impl 
        implements CircularIndexPointer {
    private int index;
    final private int max;
    final private ReentrantLock locker;
    
    public CircularIndexPointer_Impl(final int max) {
        this.max = max;
        this.index = 0;
        this.locker = new ReentrantLock();
    }
    
    /**
     * Increments the pointer in a circular fashion and returns the pointer 
     * value before the increment. Locking is used for thread safety because 
     * each thread will perform 2 updates to the index, therefore volatility 
     * and atomicity, alone, will not suffice.
     * @return current pointer value.
     */
    public int getAndIncrement() {
        int retIndex;
        locker.lock();
        try {
            retIndex = this.index;
            this.index = ++this.index >= this.max ? 0 : this.index;
        } finally { locker.unlock(); }
        return retIndex;
    }
    
}
